/**
 * 
 */
package com.wobuhekele.domain;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wobuhekele.core.AbstractDownExecute;
import com.wobuhekele.service.DownService;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * <b>需要权衡 空间与时间的平衡点  
 *   1. 数组接受的方式 : 耗时在于 内存中需要 不断的创建 巨大的数组 对于 内存来说是挑战 ,但是这样速度是最快的(主要耗时 在将已读的文件数组 不断的写入到总的数组中)
 *   2. 如果用临时文件的方式 : 耗时 在于不断的打开关闭流  用于临时文件的写入和读取(时间大概是 数组的5倍)
 *   
 *   可能是代码写的有问题 (哈哈~~!)
</p>
 * @author xchen
 * @CreateDate 2017-3-22 - 下午2:47:27 
 * @Encoding UTF-8
 * @Version 1.0
 */
public class CopyOfDemoBreakPoint extends AbstractDownExecute implements DownService{
	 

	public CopyOfDemoBreakPoint(String url,int threadSize) {
		super(url,threadSize);
				
	}

	Logger logger = LoggerFactory.getLogger(CopyOfDemoBreakPoint.class);
//	private static File sFile=new File("C:\\Users\\Administrator\\Desktop\\jisupdf_setups.txt");
//	private static File sFile=new File("C:\\Users\\Administrator\\Desktop\\jisupdf_setup_2.2.2.1001.exe");//C:\Users\chenxiong\Desktop
//	private static File sFile=new File("C:\\Users\\chenxiong\\Desktop\\SQLyog_12.3.3.exe");//jdk-7u60-ea-bin-b15-windows-x64-16_apr_2014.exe
	private static File sFile=new File("C:\\Users\\chenxiong\\Desktop\\jdk-7u60-ea-bin-b15-windows-x64-16_apr_2014.exe");//jdk-7u60-ea-bin-b15-windows-x64-16_apr_2014.exe
//	private static File sFile=new File("D:\\work pakage\\myeclipse-pro-2013-offline-installer-windows.exe");//E:\ProjectManager\Work\wcyc\ZGW\zgw_app_interface_trunk\com.wcyc.zgw.infoweb\src\main\webapp
//	private static File sFile=new File("E:\\ProjectManager\\Work\\wcyc\\ZGW\\zgw_app_interface_trunk\\com.wcyc.zgw.infoweb\\src\\main\\webapp\\DPSDK_OCX_Win32andWin64.exe");
	public static void main(String[] args) throws FileNotFoundException, Exception {
		//需要下载的文件地址
//		String urlString = "C:\\Users\\chenxiong\\Desktop\\jdk-7u60-ea-bin-b15-windows-x64-16_apr_2014.exe";
		String urlString = "http://175.6.229.74/softdl.360tpcdn.com/JisuPDF/jisupdf_setup_2.2.2.1001.exe";//
//		String urlString = "http://dldir1.qq.com/qqfile/qq/QQ8.9/19990/QQ8.9.exe";
//		String urlString = "http://42.236.10.37/softdl.360tpcdn.com/11game/11Games_1.2.4.8.exe";
//		String urlString = "http://dl.360safe.com/setup_11.0.0.2001d.exe";
		int threadSize = AbstractDownExecute.threadSize;
		//输出的文件地址
		String resultPath =  "C:\\Users\\chenxiong\\Desktop\\myeclipse测试"/*+new Date().getTime()*/+".exe";
//		String resultPath =  "C:\\Users\\Administrator\\Desktop\\myeclipse测试"/*+new Date().getTime()*/+".exe";
//		HttpURLConnection openConnection = (HttpURLConnection) new URL("http://175.6.229.74/softdl.360tpcdn.com/JisuPDF/jisupdf_setup_2.2.2.1001.exe").openConnection();
//		InputStream fileInputStream = openConnection.getInputStream();
		long begin = System.currentTimeMillis();
		
		CopyOfDemoBreakPoint demoBreakPoint = new CopyOfDemoBreakPoint(urlString,threadSize);
		System.out.println("main()==>大小"+demoBreakPoint.getContentLength());
		demoBreakPoint.SchedulerCenter(urlString, threadSize,resultPath);		
		long  end= System.currentTimeMillis();
		System.out.println("总共 耗时 + "+(end - begin));
	}
	
	//调度中心
	/**
	 * 
	 *@param userInputStream 
	 *@param threadSize 线程数量
	 *@param length  流中的数据大小
	 * @throws UnsupportedEncodingException 
	 * @Author xchen
	 * @Date 2017-3-22 - 下午2:55:48
	 */
	public void SchedulerCenter (String urlString , int threadSize ,String resultPath) throws Exception {
		CopyOfDemoBreakPoint demoBreakPoint = new CopyOfDemoBreakPoint(urlString,threadSize);
		int length = demoBreakPoint.getContentLength();
		int singleThreadExecuteSize = (length % threadSize) > 0 ? length / threadSize +1 : length / threadSize;
		
		downFile(demoBreakPoint.getUrlConnection().getInputStream(), threadSize, singleThreadExecuteSize, length,resultPath);
		
	}

	
	private List<File> createFileTemp(int tempNumber) throws IOException {
		List<File> temps = new ArrayList<File>(tempNumber);
		for(int i=0; i<tempNumber; i++){
			temps.add(i, File.createTempFile("第"+i+"个temp", "temp"));
		}
		return temps;
	}


	/**
	 * 
	 * @throws Exception 
	 * @Date 2017-3-27 - 上午10:30:40
	 */
	@Override
	public void downFile(InputStream userInputStream, int threadSize,
			int singleThreadExecuteSize ,int length,String resultPath) throws Exception {

		byte []  resultByte  = new byte[]{}; 
		
		
		ExecutorService executor = super.getExecutor();
		List<QuotoTask> quotoTasks = new ArrayList<QuotoTask>();
		for(int i =0 ; i< threadSize ; i ++){
			int startIndex = 0;
			int endIndex = 0;
			
			if(i == 0){
				startIndex = 0;
				endIndex = singleThreadExecuteSize ; 
			}
			else if (i == threadSize -1) {
				startIndex = i* singleThreadExecuteSize ;
				endIndex = length;
				singleThreadExecuteSize = endIndex -startIndex;
			}
			else{
				startIndex = i* singleThreadExecuteSize ;
				endIndex = (i+1)* singleThreadExecuteSize ;
			}
//			CountBeginEndIndex(startIndex,endIndex,singleThreadExecuteSize,threadSize,length,i);
			
			//告诉流 我只需要传多长的数据过来
			HttpURLConnection urlConnection = getNewConnection();
            StringBuilder range = new StringBuilder();
            range.append("bytes=");
            range.append(startIndex);
            range.append("-");
            range.append(endIndex);
            urlConnection.setRequestProperty("Range", range.toString());
            System.out.println("Range  == " + range.toString());
            userInputStream = urlConnection.getInputStream();
			
			QuotoTask quotoTask = new QuotoTask(startIndex , endIndex ,userInputStream ,i,singleThreadExecuteSize)	;
			quotoTasks.add(quotoTask);
			
		}
		try {
			// 把流中的数据写入到 每个线程的temp文件中
			List<Future<DownResultBean>> invokeAll = executor.invokeAll(quotoTasks);
			//将所有的临时文件LIst  解析成数组  写入到目标文件中
//			List<Future<DownResultBean>> deployTask = super.deployTask(invokeAll);
//			super.TempFileTranslateByte(deployTask,singleThreadExecuteSize,resultPath);
			executor.shutdown();
			System.out.println("ResultByte的大小" + resultByte.length );
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.toString());
		}finally{
			executor.shutdown();
		}
		
	
	}

	/**
	 * 
	 *@param startIndex  开始位置
	 *@param endIndex    结束位置
	 *@param singleThreadExecuteSize  每个线程 需要执行的大小
	 *@param threadSize  总线程数
	 *@param length      总下载的长度
	 *@param i			 当前执行的线程编号				
	 * @Author xchen
	 * @Date 2017-3-27 - 上午10:53:38
	 */
	private void CountBeginEndIndex(int startIndex, int endIndex,
			int singleThreadExecuteSize, int threadSize, int length ,int i) {
		
		if(i == 0){
			startIndex = 0;
			endIndex = singleThreadExecuteSize ; 
		}
		else if (i == threadSize -1) {
			startIndex = i* singleThreadExecuteSize ;
			endIndex = length;
		}
		else{
			startIndex = i* singleThreadExecuteSize ;
			endIndex = (i+1)* singleThreadExecuteSize ;
		}
	}
}
